package com.shrfid.rfidsdk.uitls;


import com.rfid.common.util.ByteUtil;

import java.math.BigInteger;

public class ReadTagUtils {

    public static byte[] calCrc16(byte[] bytes) {

        byte[] ret = new byte[2];
        //CRC寄存器全为1
        int CRC = 0x0000ffff;
        //多项式校验值
        int POLYNOMIAL = 0x00008408;
        int i, j;
        try {
            for (i = 0; i < bytes.length; i++) {
                CRC ^= ((int) bytes[i] & 0x000000ff);
                for (j = 0; j < 8; j++) {
                    if ((CRC & 0x00000001) != 0) {
                        CRC >>= 1;
                        CRC ^= POLYNOMIAL;
                    } else {
                        CRC >>= 1;
                    }
                }
            }
            ret[0] = (byte) CRC;
            ret[1] = (byte) (CRC >>> 8);
        } catch (Exception e) {
            e.printStackTrace();
            return ret;
        }
        return ret;
    }

    /**
     * 数组转换成十六进制字符串
     *
     * @return HexString
     */
    public static final String bytesToHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 数组转换成十六进制字符串
     *
     * @return HexString
     */
    public static final String bytesToFormatHexString(byte[] bArray) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        for (int i = 0; i < bArray.length; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2)
                sb.append(0);
            sb.append(sTemp.toUpperCase());
            sb.append(" ");
        }
        return sb.toString();
    }

    /**
     * 15693标签解析
     *
     * @return
     */
    public static String parse15693No(byte[] rowData) {
        try {
            if (rowData == null || rowData.length < 40) {
                return "";
            }

            int indexAdd = 0;
            //读取是否偏移
            if ((0x80 & rowData[0]) == 0x80) {
                //有偏移位取数据位置往后偏移一位
                indexAdd += 1;
            }

            //此种格式OID多占1字节,所以读取数据长度偏移+1
            if ((0x0F & rowData[0]) == 0x0F) {
                indexAdd += 1;
            }

            //取压缩数据长度
            int length = rowData[1 + indexAdd];

            //取数据
            byte[] dataBytes = new byte[length];

            if ((2 + indexAdd + length) > rowData.length) {
                return "";
            }

            //添加数据
            System.arraycopy(rowData, 2 + indexAdd, dataBytes, 0, length);

            //读取压缩模式
            int mode = 0x70 & rowData[0];

            //根据压缩模式解析数据
            switch (mode) {
                case 0x10://整型数压缩
                    BigInteger bigInteger = new BigInteger(bytesToHexString(dataBytes), 16);
                    return bigInteger.toString(10);
                case 0x20://数字压缩
                    String str = bytesToHexString(dataBytes);
                    if (str.endsWith("F")) {
                        str = str.substring(0, str.length() - 1);
                    }
                    return str;
                case 0x40://6bit压缩
                    String sourceData = bytesToHexString(dataBytes);
                    return unzip6bitData(sourceData);
                case 0x60://
                    String result = new String(dataBytes);
                    return result;
            }
        } catch (Exception e) {
            System.out.println("parese fail = " + ByteUtil.bytesToHexString(rowData));
//            e.printStackTrace();
        }
        return "";
    }

    /**
     * 6bit 压缩解压数据
     *
     * @param source
     * @return
     */
    public static String unzip6bitData(String source) {
        byte[] hexArray = hexString2Bytes(source);
        String binStr = byteArrToBinStr(hexArray);
        int start = 0;
        int end = 6;
        String temp = "";
        StringBuffer buffer = new StringBuffer();

        int count = source.length() * 4 / 6;
        for (int i = 0; i < count; i++) {
            temp = binStr.substring(start, end);
            start += 6;
            end += 6;

            if (temp.startsWith("1")) {
                temp = "00" + temp;
            } else if (temp.startsWith("0")) {
                temp = "01" + temp;
            }
            buffer.append(temp);
        }
        String bufferStr = buffer.toString();
        int len = bufferStr.length() / 8;
        byte[] resultArr = new byte[len];
        start = 0;
        end = 8;
        for (int i = 0; i < len; i++) {
            String str = bufferStr.substring(start, end);
            byte b = Long.valueOf(str, 2).byteValue();
            start += 8;
            end += 8;
            resultArr[i] = b;
        }
        String result = new String(resultArr);
        return result;
    }

    public static byte[] hexString2Bytes(String src) {
        byte[] ret = new byte[src.length() / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < tmp.length / 2; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }

    public static byte uniteBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }

    /**
     * byte数组转换为二进制字符串,每个字节以","隔开
     **/
    public static String byteArrToBinStr(byte[] b) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            String temp = Long.toString(b[i] & 0xff, 2);
            if (temp.length() < 8) {
                for (int j = 0; j < 8 - temp.length(); j++) {
                    result.append("0");
                }
            }
            result.append(temp);
        }
        return result.toString();
    }
}
